//!
//! ```
//! let x = 1;
//! let y: Option<i32> = None;
//! let s = stringify!{
//!     "a" => x;
//!     "b" => 2usize;
//!     "c" => 3f64;
//!     "d" => x + 6;
//!     "e" => vec![4i32, 5i32, 6i32];
//!     "f" => "hello world";
//!     "g" => Some(8);
//!     "h" => y
//! };
//! assert_eq!(s, "a=1&b=2&c=3&d=7&e[]=4&e[]=5&e[]=6&f=hello%20world");
//!
//! use std::collections::BTreeMap;
//! let mut m = BTreeMap::new();
//! m.insert("a", 1);
//! m.insert("b", 2);
//! m.insert("c", 3);
//! let s = stringify!(m);
//! assert_eq!(s,  "a=1&b=2&c=3");
//!
//! let s = stringify![
//!     ("a", 1),
//!     ("b", 2),
//!     ("c", 3)
//! ];
//! assert_eq!(s,  "a=1&b=2&c=3");
//! ```

pub mod qs;

pub use crate::qs::QueryString;
pub use crate::qs::UrlEncoding;
pub use crate::qs::QueryParam;
pub use crate::qs::QueryParams;
pub use crate::qs::QueryValue;
pub use crate::qs::ToQueryValue;


#[macro_export]
macro_rules! stringify {
    
    ($(($k:expr, $v:expr)),+) => {{
        let mut params = crate::qs::QueryParams::new();
        $(
            params.insert(crate::qs::QueryParam::new($k.to_string(), $v.to()));
        )*
        params.qs()
    }};
    ($m:expr) => {{
        $m.qs()
    }};
    ($($k:literal => $v:expr);+) => {{
        let mut params = crate::qs::QueryParams::new();
        $(
            params.insert(crate::qs::QueryParam::new($k.to_string(), $v.to()));
        )*
        params.qs()
    }};
}


#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use crate::qs::*;
    use crate::qs::value::*;

    #[test]
    fn test_stringify_common() {
        let x = 1;
        let s = stringify!{
            "a" => x;
            "b" => 2usize;
            "c" => 3f64;
            "d" => x + 6;
            "e" => vec![4i32, 5i32, 6i32];
            "f" => "hello world";
            "g" => QueryValue::Integer(8);
            "h" => QueryValue::Null
        };
        println!("{}", s);
        assert_eq!(s,  "a=1&b=2&c=3&d=7&e[]=4&e[]=5&e[]=6&f=hello%20world&g=8&h=");
    }

    #[test]
    fn test_stringify_map() {
        let mut m = BTreeMap::new();
        m.insert("a", 1);
        m.insert("b", 2);
        m.insert("c", 3);
        let s = stringify!(m);
        assert_eq!(s,  "a=1&b=2&c=3");

        let mut m = BTreeMap::new();
        m.insert("a", "hello world");
        m.insert("b", "ksd");
        m.insert("c", "turbidsoul");
        let s = stringify!(m);
        assert_eq!(s,  "a=hello%20world&b=ksd&c=turbidsoul");
    }

    #[test]
    fn test_stringify_tuple() {
        let x = 1;
        let s = stringify![
            ("a", x),
            ("b", 2i32),
            ("c", 3i32),
            ("d", x + 6),
            ("e", vec![4i32, 5i32, 6i32]),
            ("f", "hello world"),
            ("g", QueryValue::Null)
        ];
        assert_eq!(s,  "a=1&b=2&c=3&d=7&e[]=4&e[]=5&e[]=6&f=hello%20world&g=");
    }
}
